﻿using AutoRetailsDLL.Workers.PinDuoDuo;
using AutoRetailsEXE;
using CefSharp;
using CefSharp.WinForms;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using System.Xml.Linq;

namespace AutoRetailsDLL.Workers
{
    public  class WorkersBase
    {
        protected WorkResult result = WorkResult.WorkFailed();
        protected bool Is判断Login状态 = false;
        //不可直接用
        protected bool Is登录 = false;
        protected static ChromePage chromePage = new ChromePage();
        /// <summary>
        /// 填空等待时间
        /// </summary>
        protected int wordWaitTime { get; set; } = 500;
        //点击list等待时间   （需要配置）
        protected int listClickWaitTime { get; set; } = 1000;
        //选择了数据之后等待时间（200 跟 500 之间关系不大）
        protected int listSelectValueWaitTime { get; set; } = 200; 
        /// <summary>
        /// 图片等待时间
        /// </summary>
        protected int pictureWaitTime { get; set; } = 2000;
        /// <summary>
        /// 超时时间(默认一百秒)
        /// </summary>
        protected int outTime { get; set; } = 200000;
        /// <summary>
        /// 请求开始时间
        /// </summary>
        protected DateTime beginTime { get; set; }
        /// <summary>
        /// 请求结束时间
        /// </summary>
        protected DateTime endTime { get; set; } 
        protected ChromiumWebBrowser GetChromiumWebBrowser()
        {
            return chromePage.GetChromiumWebBrowser();
        }
        protected void 点击屏幕()
        {
            //点一下屏幕
            GetChromiumWebBrowser().GetBrowserHost().SendMouseClickEvent(1, 1, MouseButtonType.Left, false, 1, CefEventFlags.None);
        }
        protected void 点击屏幕中央()
        {
            //点一下屏幕
            GetChromiumWebBrowser().GetBrowserHost().SendMouseClickEvent(chromePage.Width/2, chromePage.Height/2, MouseButtonType.Left, false, 1, CefEventFlags.None);
        }
        protected void 点击屏幕最上边中间()
        {
            //点一下屏幕
            GetChromiumWebBrowser().GetBrowserHost().SendMouseClickEvent(1000, 10, MouseButtonType.Left, false, 1, CefEventFlags.None);
        }
        protected void 滚动屏幕()
        {
            //点一下屏幕
            GetChromiumWebBrowser().GetBrowserHost().SendMouseWheelEvent(new MouseEvent(0, -600, CefEventFlags.None),0, -600);
        }
        public void 点击屏幕_左键(int x, int y)
        {
            GetChromiumWebBrowser().GetBrowserHost().SendMouseClickEvent(x, y, MouseButtonType.Left, false, 1, CefEventFlags.None);
            GetChromiumWebBrowser().GetBrowserHost().SendMouseClickEvent(x, y, MouseButtonType.Left, true, 1, CefEventFlags.None);
        }  
        public void 点击元素_左键(string ele_js,int wait_time=0,bool click_mid=false) 
        {
            ElementInfo elementInfo = 获取元素坐标(ele_js);
            if (click_mid)
            {
                elementInfo.X = elementInfo.X+ elementInfo.Width/2;
                elementInfo.Y = elementInfo.Y+ elementInfo.Height/2;
            }
            else
            {
                RandomXY(elementInfo);
            }

            点击屏幕_左键(elementInfo.X, elementInfo.Y);
            WaitWebBrowserAsync(wait_time);
        }
        public void 点击元素_右键(string ele_js, int wait_time = 0, bool click_mid = false)
        {
            ElementInfo elementInfo = 获取元素坐标(ele_js);
            if (click_mid)
            {
                elementInfo.X = elementInfo.X + elementInfo.Width / 2;
                elementInfo.Y = elementInfo.Y + elementInfo.Height / 2;
            }
            else
            {
                RandomXY(elementInfo);
            }

            点击屏幕_右键(elementInfo.X, elementInfo.Y);
            WaitWebBrowserAsync(wait_time);
        }
        public void 点击屏幕_右键(int x, int y)
        {

            //点一下屏幕
            GetChromiumWebBrowser().GetBrowserHost().SendMouseClickEvent(x, y, MouseButtonType.Right, true, 1, CefEventFlags.None);
        }
        public void 点击元素_JS(string ele_js, int wait_time = 0, bool click_mid = false)
        {
            string js = @$"            
            var element = {ele_js};
            element.click()";
            ExecuteScriptAndWaitAsync(js, wait_time);
        }
        public void 选择下拉元素_JS(string ele_text, int wait_time = 0, bool click_mid = false)
        {
            string js = @$"            
            var element = getElementByText('li', '{ele_text}');
            element.click()";
            ExecuteScriptAndWaitAsync(js);
        }

        public void 点击元素_输入(string ele_js, string text, int wait_time = 0)
        {
            ElementInfo elementInfo = 获取元素坐标(ele_js);
            RandomXY(elementInfo);
            点击屏幕_左键(elementInfo.X, elementInfo.Y);
            WaitWebBrowserAsync(500);
            键盘输入(text, wait_time);
        }
        public void 键盘输入(string text, int wait_time=0)
        {
            if (string.IsNullOrEmpty(text))
            {
                return;
            }
            foreach (var item in text)
            {
                GetChromiumWebBrowser().GetBrowserHost().SendKeyEvent((int)CefSharp.Wpf.WM.CHAR, (int)item, 0);
                if (wait_time>0)
                {
                    WaitWebBrowserAsync(wait_time);
                }

            }
        }
        public void RandomXY(ElementInfo elementInfo) 
        {
            Random random = new Random();
            elementInfo.X= random.Next(elementInfo.X+ elementInfo.Width/10, elementInfo.X+elementInfo.Width/10*9);
            elementInfo.Y = random.Next(elementInfo.Y + elementInfo.Height / 10, elementInfo.Y + elementInfo.Height / 10 * 9);
        }
        public class ElementInfo 
        {
            public int X { get; set; }
            public int Y { get; set; }
            public int Height { get; set; }
            public int Width { get; set; }
        }
        public ElementInfo 获取元素坐标(string ele_js)
        {
            ElementInfo elementInfo = new ElementInfo();
            try
            {               
                string js = @"(function(){
                var ele=" + ele_js + @";
                const rect = ele.getBoundingClientRect();
                return rect.left+'-'+rect.top+'-'+rect.height+'-'+rect.width
                })() ";
                string checkresult = EvaluateScriptAsync(js);
                if (checkresult==null)
                {
                    return elementInfo;
                }
                List<string> X_Y_string = checkresult.Split('-').ToList();
                elementInfo.X = (int)double.Parse(X_Y_string[0]);
                elementInfo.Y = (int)double.Parse(X_Y_string[1]);
                elementInfo.Height = (int)double.Parse(X_Y_string[2]);
                elementInfo.Width = (int)double.Parse(X_Y_string[3]);
                return elementInfo;
            }
            catch (Exception ee)
            {
                LogHelper.WriteLog("获取元素坐标发生异常", ee);
                return elementInfo;
            }
           
        }
        public void 设置元素居中(string ele_js) 
        {
            string js = @"            
            var element = "+ ele_js + @";
            var x = element.getBoundingClientRect().left + window.scrollX;
            var y = element.getBoundingClientRect().top/2 + window.scrollY;
            window.scrollTo(x, y)";
            ExecuteScriptAndWaitAsync(js);
        }
        public void 设置元素居中2(string ele_js)
        {

            string js = @"            
            var element = " + ele_js + @";
            element.scrollIntoView({ behavior: 'smooth' });";
            ExecuteScriptAndWaitAsync(js);
            WaitWebBrowserAsync(1000);
        }
        public void 执行命令(string js)
        {
            string result = EvaluateScriptAsync(js);
            MessageBox.Show(result);
        }
        
        protected void SetConfig(WorkerConfig workerConfig) 
        {
            if (workerConfig.wordWaitTime>0) 
            {
                wordWaitTime = workerConfig.wordWaitTime;
            }
            if (workerConfig.pictureWaitTime>0)
            {
                pictureWaitTime = workerConfig.pictureWaitTime;
            }
            if (workerConfig.outTime>0)
            {
                outTime = workerConfig.outTime;
            }

            SetBeginAndEndTime();
        }
        protected void SetConfig(string json)
        {
            WorkerConfig workerConfig=JsonConvert.DeserializeObject<WorkerConfig>(json);
            SetConfig(workerConfig);
        }

        protected void SetBeginAndEndTime() 
        {
            beginTime= DateTime.Now;
            endTime= beginTime.AddMilliseconds(outTime);
        }
        /// <summary>
        /// 等待多少毫秒
        /// </summary>
        /// <param name="millisecond"></param>
        /// <returns></returns>
        protected void WaitWebBrowserAsync(int millisecond)
        {
            Task task = Task.Run(() =>
            {
                Thread.Sleep(millisecond);
            });
            task.Wait();
            //ManualResetEvent manualEvent = new ManualResetEvent(false);

            //EventHandler<LoadingStateChangedEventArgs> handler = null;
            //handler = (sender, args) =>
            //{
            //    if (!args.IsLoading)
            //    {
            //        GetChromiumWebBrowser().LoadingStateChanged -= handler;
            //        manualEvent.Set();
            //    }
            //};
            //GetChromiumWebBrowser().LoadingStateChanged += handler;

            //manualEvent.WaitOne(millisecond);
        }
        /// <summary>
        /// 等待页面加载完成
        /// </summary>
        /// <returns></returns>
        protected void WaitWebBrowserLoadingAsync() 
        {
            Task task = Task.Run(() => {
                while (GetChromiumWebBrowser().IsLoading)
                {
                    Thread.Sleep(500);
                }
            });
            task.Wait();
        }
        public void WaitForLoad(int timeoutMs = 30000)
        {
            ManualResetEvent manualEvent = new ManualResetEvent(false);

            EventHandler<LoadingStateChangedEventArgs> handler = null;
            handler = (sender, args) =>
            {
                if (!args.IsLoading)
                {
                    GetChromiumWebBrowser().LoadingStateChanged -= handler;
                    manualEvent.Set();
                }
            };
            GetChromiumWebBrowser().LoadingStateChanged += handler;

            manualEvent.WaitOne(timeoutMs);
        }

        /// <summary>
        /// 通过判断页面判断
        /// </summary>
        /// <returns></returns>
        protected bool IsLogin2()
        {
            bool islogin = false;
            if (!GetChromiumWebBrowser().Address.Contains("login"))
            {
                islogin = true;
            }
            LogHelper.WriteLog($"登录验证：{islogin}");
            return islogin;
        }
        /// <summary>
        /// 执行js并返回结果
        /// </summary>
        /// <param name="js"></param>
        /// <returns></returns>
        protected string EvaluateScriptAsync(string js) 
        {
            try
            {
                var task = GetChromiumWebBrowser().EvaluateScriptAsync(js);
                task.Wait();
                return task.Result?.Result?.ToString();
            }
            catch (Exception)
            {

                return null;
            }
            
        }
        /// <summary>
        /// 执行js并等待
        /// </summary>
        /// <param name="js"></param>
        /// <returns></returns>
        protected  void ExecuteScriptAndWaitAsync(string js,int milliseconds=0)
        {
            GetChromiumWebBrowser().ExecuteScriptAsync(js);
            if (milliseconds>0)
            {
                WaitWebBrowserAsync(milliseconds);
            }
        }
        /// <summary>
        /// 设置事件
        /// </summary>
        /// <returns></returns>
        protected void SetUploadFileDialogHandler()
        {
            GetChromiumWebBrowser().DialogHandler = new UploadFileDialogHandler();
            GetChromiumWebBrowser().JsDialogHandler = new JsDialogHandler();

        }

        /// <summary>
        /// 设置文件上传路径
        /// </summary>
        /// <param name="file_paht_list"></param>
        protected void SetUploadFilePath(List<string> file_paht_list)
        {
            UploadFileDialogHandler.file_paht_list = file_paht_list;
        }
        protected void 执行必备JS()
        {
            LogHelper.WriteLog($"执行必备JS");
            GetChromiumWebBrowser().ExecuteScriptAsync(JavaScriptString.getElementByText);
            GetChromiumWebBrowser().ExecuteScriptAsync(JavaScriptString.getElementByText2);
            GetChromiumWebBrowser().ExecuteScriptAsync(JavaScriptString.setInputValue);
            GetChromiumWebBrowser().ExecuteScriptAsync(JavaScriptString.getElementByClassAndText);
            GetChromiumWebBrowser().ExecuteScriptAsync(JavaScriptString.getElementByClassAndText2); 
            GetChromiumWebBrowser().ExecuteScriptAsync(JavaScriptString.getElementByTextAll);
            LogHelper.WriteLog($"执行必备JS完成");
        }
    }
}
